package com.turing.post.capitalaccounts.impl;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.turing.post.capitalaccounts.util.FundsReportDao;
import com.turing.post.capitalaccounts.util.FundsReportObj;
import com.turing.post.cardmanagement.util.CardEventLogDao;
import com.turing.post.organization.util.IssueBranch;
import com.turing.post.organization.util.IssueBranchDao;
import com.turing.post.organization.util.IssueCompany;
import com.turing.post.organization.util.IssueCompanyDao;
import com.turing.post.organization.util.SaleBranch;
import com.turing.post.organization.util.SaleBranchDao;
import com.turing.post.report.util.BranchDaySett;
import com.turing.post.report.util.BranchDaySettDao;
import com.turing.post.salesmanage.util.BranchDaySett_Obj;
import com.turing.post.salesmanage.util.DepositOrderPaidDetailDao;
import com.turing.post.salesmanage.util.SaleOrderPaidDetailDao;
import com.turing.post.util.PCPSUtil;
import com.turing.post.util.PCPSWebInput;

@Stateless(mappedName = "capitalaccounts.impl.FundsReportDaoImpl")
@Remote
@Local
public class FundsReportDaoImpl implements FundsReportDao {
	/**
	 * 实体管理器
	 * 
	 * @see javax.persistence.EntityManager
	 */
	@PersistenceContext
	protected EntityManager _em;

	/**
	 * 银行入账流水
	 */
	@EJB(mappedName = "report.impl.BranchDaySettDaoImpl")
	private BranchDaySettDao branchDaySettDaoImpl;

	/**
	 * 销售机构
	 */
	@EJB(mappedName = "organization.impl.SaleBranchDaoImpl")
	private SaleBranchDao saleBranchDaoImpl;

	/**
	 * 发卡机构
	 */
	@EJB(mappedName = "organization.impl.IssueBranchDaoImpl")
	private IssueBranchDao issueBranchDaoImpl;

	/**
	 * 卡特殊业务日志
	 */
	@EJB(mappedName = "cardmanagement.impl.CardEventLogDaoImpl")
	private CardEventLogDao cardEventLogDaoImpl;

	/**
	 * 销售单付款
	 */
	@EJB(mappedName = "salesmanage.impl.SaleOrderPaidDetailDaoImpl")
	private SaleOrderPaidDetailDao saleOrderPaidDetailDaoImpl;

	/**
	 * 充值单付款
	 */
	@EJB(mappedName = "salesmanage.impl.DepositOrderPaidDetailDaoImpl")
	private DepositOrderPaidDetailDao depositOrderPaidDetailDaoImpl;

	/**
	 * 发卡商
	 */
	@EJB(mappedName = "organization.impl.IssueCompanyDaoImpl")
	private IssueCompanyDao issueCompanyDaoImpl;

	/**
	 * 获取某发卡商下发卡机构某段时间已审核资金
	 * 
	 * @param webInput
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<FundsReportObj> getIssueBranchAuditFunds(PCPSWebInput webInput,
			String startDate, String endDate) {
		List<FundsReportObj> return_list = new ArrayList<FundsReportObj>();
		if (webInput == null || PCPSUtil.isEmpty(startDate)
				|| PCPSUtil.isEmpty(endDate)) {
			return return_list;
		}
		String issueCompanyNo = PCPSUtil.getIssueCompanyNo(webInput);
		String sql = "with v as ( select t.createbranchno, nvl(sum(t.voucheramount), 0)  as voucheramount "
				+ " from bankaccountdetail t "
				+ " where t.authtrandate is not null"
				+ " and t.createbranchno like ?1 "
				+ " and t.authtrandate >=to_date(?2,'yyyy-MM-dd')"
				+ " and t.authtrandate <=to_date(?3,'yyyy-MM-dd')"
				+ " and t.status in('0','1')"
				+ " group by t.createbranchno ) "
				+ " select i.issuebranchno, i.issuebranchname, sum(v.voucheramount) "
				+ " from v, issuebranch i, sysbranchsubord s "
				+ " where s.branchno = i.issuebranchno and i.allowactivate = '1' "
				+ " and i.issuebranchno like ?1 "
				+ " and s.subbranchno = v.createbranchno group by i.issuebranchno, i.issuebranchname";
		Query query = _em.createNativeQuery(sql);
		query.setParameter(1, issueCompanyNo + "%");
		query.setParameter(2, startDate);
		query.setParameter(3, endDate);
		List<Object[]> obj_list = query.getResultList();
		if (obj_list == null || obj_list.size() <= 0) {
			return return_list;
		}
		FundsReportObj obj = null;
		for (int i = 0; i < obj_list.size(); i++) {
			obj = new FundsReportObj();
			obj.setIssueBranchNo(obj_list.get(i)[0].toString());
			obj.setIssueBranchName(obj_list.get(i)[1].toString());
			obj.setFunds(obj_list.get(i)[2].toString());
			return_list.add(obj);
		}
		return return_list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<FundsReportObj> getIssueBranchSendCredit(PCPSWebInput webInput,
			String startDate, String endDate) {
		List<FundsReportObj> return_list = new ArrayList<FundsReportObj>();
		if (webInput == null || PCPSUtil.isEmpty(startDate)
				|| PCPSUtil.isEmpty(endDate)) {
			return return_list;
		}
		String sql = "select ib.issuebranchno,ib.issuebranchname,nvl(sum(t.amount),0)"
				+ " from creditaccdetail t,issuebranch ib"
				+ " where t.issuebranchno = ib.issuebranchno"
				+ " and t.issuebranchno like ?1"
				+ " and t.trandate >=to_date(?2,'yyyy-MM-dd')"
				+ " and t.trandate <=to_date(?3,'yyyy-MM-dd')"
				+ " and t.trantype = '10'"
				+ " group by ib.issuebranchno,ib.issuebranchname"
				+ " order by ib.issuebranchno";
		Query query = _em.createNativeQuery(sql);
		query.setParameter(1, webInput.getOperBranchNo() + "%");
		query.setParameter(2, startDate);
		query.setParameter(3, endDate);
		List<Object[]> obj_list = query.getResultList();
		if (obj_list == null || obj_list.size() <= 0) {
			return return_list;
		}
		FundsReportObj obj = null;
		for (int i = 0; i < obj_list.size(); i++) {
			obj = new FundsReportObj();
			obj.setIssueBranchNo(obj_list.get(i)[0].toString());
			obj.setIssueBranchName(obj_list.get(i)[1].toString());
			obj.setCredit(obj_list.get(i)[2].toString());
			return_list.add(obj);
		}
		return return_list;
	}

	@Override
	public List<FundsReportObj> getIssueBranchFee(PCPSWebInput webInput,
			String startDate, String endDate) {
		List<FundsReportObj> return_list = new ArrayList<FundsReportObj>();
		if (webInput == null || PCPSUtil.isEmpty(startDate)
				|| PCPSUtil.isEmpty(endDate)) {
			return return_list;
		}
		// 存放数据
		Map<String, FundsReportObj> feeMap = new HashMap<String, FundsReportObj>();
		IssueCompany issueCompany = issueCompanyDaoImpl
				.getIssueCompanyByIssueCompanyNo(PCPSUtil
						.getIssueCompanyNo(webInput));
		// 获取发卡商下属所有的发卡机构(key), value为销售机构的sql in语句部分
		Map<String, String> issuebrchMap = saleBranchDaoImpl
				.getSaleBrchMapByIssueCompanyNo(issueCompany
						.getIssueCompanyNo());
		if (issuebrchMap == null || issuebrchMap.isEmpty()) {
			return return_list;
		}
		BigInteger fee = BigInteger.ZERO;
		FundsReportObj obj = null;
		// 循环从销售机构日结表中取手续费
		for (Map.Entry<String, String> entry : issuebrchMap.entrySet()) {
			fee = branchDaySettDaoImpl.getFeeTotalBySaleBrchNos(entry
					.getValue(), startDate, endDate);
			obj = new FundsReportObj();
			IssueBranch ib = issueBranchDaoImpl
					.getIssueBranchByIssueBranchNo(entry.getKey());
			obj.setIssueBranchNo(ib.getIssueBranchNo());
			obj.setIssueBranchName(ib.getIssueBranchName());
			obj.setFee(fee);
			feeMap.put(entry.getKey(), obj);
		}
		//
		// 终止日期
		Date eDate = PCPSUtil.getDateYMDByString(endDate);
		// 当前账务日期,取发卡商账务日期
		Date nDate = issueCompany.getTranDate();
		// 如果终止日期比当前日期晚1天,则从销售单,充值单,卡特殊业务中取当天的手续费
		while (eDate.compareTo(nDate) >= 0) {
			fee = BigInteger.ZERO;
			for (Map.Entry<String, String> entry : issuebrchMap.entrySet()) {
				if (feeMap.get(entry.getKey()) == null) {
					continue;
				}
				// 取某发卡机构下所有销售机构信息
				List<SaleBranch> saleList = saleBranchDaoImpl
						.getSaleBrchByIssueBrchNo(entry.getKey());
				if (saleList == null) {
					continue;
				}
				for (SaleBranch sb : saleList) {
					// 销售单手续费
					List<BranchDaySett_Obj> sale_list_obj = saleOrderPaidDetailDaoImpl
							.getBranchDaySettByBranchNoAndTranDate(sb
									.getSaleBranchNo(), eDate);
					if (sale_list_obj != null) {
						for (BranchDaySett_Obj sale_obj : sale_list_obj) {
							fee = fee.add(sale_obj.getCashFee()).add(
									sale_obj.getTranFee()).add(
									sale_obj.getChequeFee());
						}
					}
					// 充值单手续费
					List<BranchDaySett_Obj> deposit_list_obj = depositOrderPaidDetailDaoImpl
							.getBranchDaySettByBranchNoAndTranDate(sb
									.getSaleBranchNo(), eDate);
					if (deposit_list_obj != null) {
						for (BranchDaySett_Obj bds_obj : deposit_list_obj) {
							fee = fee.add(bds_obj.getCashFee()).add(
									bds_obj.getTranFee()).add(
									bds_obj.getChequeFee());
						}
					}
					// 卡特殊业务手续费
					List<BranchDaySett> special_list = getBranchDaySettByBranchNoAndTranDate(
							issueCompany.getIssueCompanyNo(), sb
									.getSaleBranchNo(), eDate);
					if (special_list != null) {
						for (BranchDaySett bds_obj : special_list) {
							fee = fee.add(bds_obj.getCashFee());
						}
					}
				}

				obj = new FundsReportObj();
				obj = feeMap.remove(entry.getKey());
				obj.setFee(obj.getFee().add(fee));
				feeMap.put(entry.getKey(), obj);
			}
			// 减终止日期
			eDate = PCPSUtil.getSubductionDays(eDate, -1);
		}

		// 循环封装return_list
		for (Map.Entry<String, FundsReportObj> entry : feeMap.entrySet()) {
			obj = new FundsReportObj();
			obj = feeMap.get(entry.getKey());
			if (obj != null) {
				return_list.add(obj);
			}
		}
		return return_list;
	}

	/**
	 * 获取机构日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商号
	 * @param branchNo
	 *            机构号
	 * @param tranDate
	 *            帐务日期
	 * @return
	 */
	private List<BranchDaySett> getBranchDaySettByBranchNoAndTranDate(
			String issueCompanyNo, String branchNo, Date tranDate) {
		List<Object[]> objlist = cardEventLogDaoImpl
				.getBranchDaySettByBranchNoAndTranDate(issueCompanyNo,
						branchNo, tranDate);
		List<BranchDaySett> bdslist = new ArrayList<BranchDaySett>();
		for (Object[] objarr : objlist) {
			BranchDaySett bds = new BranchDaySett();
			bds.setCashFee(new BigInteger(objarr[7].toString()));
			bdslist.add(bds);
		}
		return bdslist;
	}
}
